package com.skillworld.webapp.model.enrollment;

import java.sql.Time;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;

import org.springframework.stereotype.Repository;

import com.skillworld.webapp.model.course.Course;
import com.skillworld.webapp.model.course.CourseDao;
import com.skillworld.webapp.model.department.Department;
import com.skillworld.webapp.model.enrollment.ReleasedExam.State;
import com.skillworld.webapp.model.tutorial.MarkedTutorial.Mark;
import com.skillworld.webapp.model.user.User;
import com.skillworld.webapp.model.util.dao.GenericDaoHibernate;


@Repository("examinationDao")
public class ExaminationDaoHibernate 
        extends GenericDaoHibernate<Examination,Long>
        implements ExaminationDao 
{

	public List<Examination> findByUser(Long idUser){
	        @SuppressWarnings("unchecked")
	        List<Examination> list = (List<Examination>) getSession().createQuery(
	                "SELECT sl FROM Examination sl " +
	                "where sl.idUser = :idU ")
	                .setFirstResult(0)
	                .setParameter("idU", idUser)
	                .list();
	        return list;
	}

	public Examination find(long lessonId, long userId)
	{
        return(Examination) 
            getSession().createQuery("SELECT ex FROM Examination ex " +
        	                         " WHERE ex.enrollment.student.userId = :userId " +
        		                     "   AND ex.lesson.lessonId = :lessonId ")
                                .setParameter("userId", userId)
                                .setParameter("lessonId", lessonId)
                                .uniqueResult();
	}

	public boolean finishCourse(Long idCourse){
        @SuppressWarnings("unchecked")
        List<Examination> list= (List<Examination>) getSession().createQuery(
        		"select ls from lesson l, Examination ls " +
        		"where l.idLesson = ls.idLesson and l.idCourse = idC")
                .setFirstResult(0)
                .setParameter("idC", idCourse);	
                
		return finish(list);
	}
	
	public boolean finish(List<Examination> list){
		boolean flag = false; 
		if (list == null) return flag; 
	
		flag = true; 
		
			for(Examination sl : list){
				if (sl.getFinishDate() == null) flag = false;    
			}
	
		return flag; 
	}
	
	
    private Criteria buildSearchQuery(Long userId, Long courseId, 
            User.Role role, ReleasedExam.State state,  
            List<Long> lessons)
    {
        Criteria q = getSession().createCriteria(Examination.class);

        q.createAlias("lesson", "l");
        q.add(Restrictions.eq("l.course.courseId", courseId));

        switch(role)
        {
            case STUDENT:
                q.add(Restrictions.eq("enrollment.student.userId", userId));
                break;
    
            case MASTERCOACH:
                q.createAlias("l.course", "c");
                q.add(Restrictions.eq("c.author.userId", userId));
                break;
        }

        if(state != null)
        { q.add(Restrictions.eq("releasedExam.state", state)); }

        if(lessons != null)
        { q.add(Restrictions.in("l.lessonId", lessons)); }

        return  q;
    }

	public long numberOfExaminations(long userId, long courseId, 
	                                    User.Role role, 
	                                    ReleasedExam.State state,
	                                    List<Long> lessons)
	{
        return(Long) buildSearchQuery(userId, courseId, role, state, lessons)
                        .setProjection(Projections.rowCount())
                        .uniqueResult();

	}

    @SuppressWarnings("unchecked")
    public List<Examination> listExaminations(long userId, long courseId, 
                                                User.Role role, 
                                                ReleasedExam.State state,  
                                                List<Long> lessons, 
                                                int startIndex, int count)
    {
        return(List<Examination>) 
            buildSearchQuery(userId, courseId, role, state, lessons)
                .setFirstResult(startIndex)
                .setMaxResults(count)
                .list();
    }
}
